////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_CONCURRENCY_THREAD_H__
#define __WN_CONCURRENCY_THREAD_H__

#include "WNCore/inc/WNPlatform.h"
#include "WNCore/inc/WNTypes.h"

#ifdef _WN_WINDOWS
    #include <windows.h>
#elif defined _WN_LINUX
    #include <pthread.h>
#endif

typedef WN_VOID* (*WN_THREAD_FUNCTION_T)(WN_VOID*);

namespace WNConcurrency {
    class WNThread {
    public:
        WN_INLINE WNThread();
        WN_INLINE WNThread(WN_THREAD_FUNCTION_T _function, WN_VOID* _parameters = WN_NULL);
        WN_INLINE ~WNThread();

        WN_INLINE WN_BOOL Execute();

        WN_INLINE WN_BOOL SetStartRoutine(WN_THREAD_FUNCTION_T _function, WN_VOID* _parameters = WN_NULL);

        WN_INLINE WN_BOOL SetAffinity(WN_SIZE_T _affinity);
        WN_INLINE WN_BOOL SetPriority(WN_UINT32 _priority);

        WN_INLINE WN_SIZE_T GetAffinity() const;
        WN_INLINE WN_UINT32 GetPriority() const;

        WN_INLINE WN_BOOL GetReturn(WN_VOID** _return) const;

        WN_INLINE WN_UINT32 GetID() const;

        WN_INLINE WN_BOOL IsValid() const;
        WN_INLINE WN_BOOL IsReady() const;
        WN_INLINE WN_BOOL IsRunning() const;
        WN_INLINE WN_BOOL IsFinished() const;

        WN_INLINE WN_BOOL Join(WN_UINT32 _milliseconds = -1) const;

    private:
        #ifdef _WN_WINDOWS
            static WN_INLINE DWORD WINAPI Starter(WN_VOID* _thread);
        #elif defined _WN_LINUX
            static WN_INLINE WN_VOID* Starter(WN_VOID* _thread);
        #endif

    private:
        #ifdef _WN_WINDOWS
            HANDLE mHandle;
        #elif defined _WN_LINUX
            pthread_t mThread;
        #endif

        WN_UINT32 mID;

        WN_UINT32 mPriority;
        WN_SIZE_T mAffinity;

        WN_THREAD_FUNCTION_T mFunction;
        WN_VOID* mParameters;
        WN_VOID* mReturn;

        WN_UINT8 mState;
    };

    WN_INLINE WN_VOID WNThreadYield();
    WN_INLINE WN_VOID WNThreadSleep(WN_UINT32 _milliseconds);
}

#include "WNConcurrency/inc/WNThread.inl"

#endif // __WN_CONCURRENCY_THREAD_H__